package com.qttaudio.sdk.video;

import android.content.Context;
import android.graphics.ImageFormat;
import android.hardware.Camera;
import android.hardware.Camera.Size;
import android.util.AttributeSet;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.List;

public final class QttCameraView extends SurfaceView implements SurfaceHolder.Callback, Camera.PreviewCallback, VideoCapturer {

	protected ByteBuffer mFrameBytebuf = null;

	private int 						defaultWidth  = 640 ;
	private int 						defaultHeight = 480 ;
	
	private QttCameraViewListener cameraListenrer = null ;
	private Camera 						cameraObject = null ;
	private int							previewFormat = -1 ;
	private int 						priviewWidth  = 0 ;
	private int 						priviewHeight = 0 ;
	private byte[] 						priviewBuffer = null ;
//	private byte[] 						rotateBuffer = null ;
	private boolean 					previewDoing  = false ;
	private Context context = null;
	
	public QttCameraView(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		this.context = context;
		initCameraView();
	}

	public QttCameraView(Context context, AttributeSet attrs) {
		super(context, attrs);
		this.context = context;
		initCameraView();
	}

	public QttCameraView(Context context) {
		super(context);
		this.context = context;
		initCameraView();
	}


	private void initCameraView() {
		this.getHolder().addCallback(this);
	}

	public void OpenCamera(boolean on) {
		if (on) {
			try {
				this.cameraObject = Camera.open(Camera.CameraInfo.CAMERA_FACING_FRONT);
			} catch (Exception e) {
				e.printStackTrace() ;
			}

			if(cameraObject == null)
				return ;
			cameraObject.setDisplayOrientation(90);

			Camera.Parameters params = cameraObject.getParameters();
			//params.setPreviewFormat(ImageFormat.YV12) ;
			params.setPreviewFormat(ImageFormat.NV21) ;
			params.setPreviewFpsRange(20,30);
			//params.setRotation(180);
			params.setPreviewFpsRange(15*1000, 30*1000);
			params.setPreviewFrameRate(25);
			//params.setPreviewFormat(ImageFormat.YUV_420_888);

			this.previewFormat = params.getPreviewFormat();

			//cameraObject.setParameters(params);

			List<Size> preSizelist = params.getSupportedPictureSizes();
			boolean supportDefault = false;
			for (Size size : preSizelist) {
				Log.d("qtt_debug", "support width="+size.width+", height="+size.height);
				if (size.width == defaultWidth && size.height == defaultHeight) {
					supportDefault = true;
					break;
				}
			}

			if (!supportDefault)
				defaultHeight = 480; //640x480一般都支持，这里应该取640x360最相近合适的，暂时先写死吧
			params.setPreviewSize(defaultWidth, defaultHeight);

			this.cameraObject.setParameters(params);
			//this.cameraObject.setDisplayOrientation(90);

			this.priviewWidth = params.getPreviewSize().width;
			this.priviewHeight = params.getPreviewSize().height;
			if (mFrameBytebuf == null)
				mFrameBytebuf = ByteBuffer.allocateDirect((int)(this.priviewWidth * this.priviewHeight * 1.5));

			this.priviewBuffer = new byte[(int)(this.priviewWidth * this.priviewHeight * 1.5)];
//		this.rotateBuffer = new byte[(int)(this.priviewWidth * this.priviewHeight * 1.5)];

			this.cameraObject.addCallbackBuffer(this.priviewBuffer);
			this.cameraObject.setPreviewCallbackWithBuffer(this);
			try {
				this.cameraObject.setPreviewDisplay(getHolder());
			} catch (IOException e) {
				e.printStackTrace();
			}
		} else {
			if (this.cameraObject != null) {
				this.cameraObject.release();
				this.cameraObject = null;
			}
		}
	}

	public void startPreview(boolean on) {
		if(this.cameraObject != null)
		{
			if(!on)
			{
				this.cameraObject.stopPreview();
				this.previewDoing = false ;
			}
			else
			{
				this.cameraObject.startPreview();
				this.previewDoing = true ;
			}
		}
	}

	public void rotateNV21(byte[] input, byte[] output, int width, int height, int rotation) {
		boolean swap = (rotation == 90 || rotation == 270);
		boolean yflip = (rotation == 90 || rotation == 180);
		boolean xflip = (rotation == 270 || rotation == 180);
		for (int x = 0; x < width; x++) {
			for (int y = 0; y < height; y++) {
				int xo = x, yo = y;
				int w = width, h = height;
				int xi = xo, yi = yo;
				if (swap) {
					xi = w * yo / h;
					yi = h * xo / w;
				}
				if (yflip) {
					yi = h - yi - 1;
				}
				if (xflip) {
					xi = w - xi - 1;
				}
				output[w * yo + xo] = input[w * yi + xi];
				int fs = w * h;
				int qs = (fs >> 2);
				xi = (xi >> 1);
				yi = (yi >> 1);
				xo = (xo >> 1);
				yo = (yo >> 1);
				w = (w >> 1);
				h = (h >> 1);
				// adjust for interleave here
				int ui = fs + (w * yi + xi) * 2;
				int uo = fs + (w * yo + xo) * 2;
				// and here
				int vi = ui + 1;
				int vo = uo + 1;
				output[uo] = input[ui];
				output[vo] = input[vi];
			}
		}
	}

	public void surfaceCreated(SurfaceHolder holder) {
		if (cameraObject != null) {
			try {
				this.cameraObject.setPreviewDisplay(holder);
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	public void onPreviewFrame(byte[] data, Camera camera) {
		camera.addCallbackBuffer(this.priviewBuffer);
//		rotateNV21(this.priviewBuffer, this.rotateBuffer, this.priviewWidth, this.priviewHeight, 270);
		mFrameBytebuf.clear();
		mFrameBytebuf.put(this.priviewBuffer, 0, this.priviewBuffer.length);
		nativePutFrame(mFrameBytebuf, this.priviewBuffer.length, priviewWidth, priviewHeight);
		if(this.cameraListenrer != null) {
			this.cameraListenrer.onCameraPreviewFrame(this.priviewWidth, this.priviewHeight, this.priviewBuffer, this.previewFormat) ;
		}
	}


	public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {

	}

	public void surfaceDestroyed(SurfaceHolder holder) {
		if (this.cameraObject != null) {
			this.cameraObject.stopPreview();
			this.cameraObject.release();
			this.cameraObject = null;
		}
	}

	public QttCameraViewListener getCameraListenrer() {
		return cameraListenrer;
	}

	public void setCameraListenrer(QttCameraViewListener cameraListenrer) {
		this.cameraListenrer = cameraListenrer;
	}

	@Override
	public int width() {
		return defaultHeight;
	}

	@Override
	public int height() {
		return defaultWidth;
	}

	@Override
	public int fps() {
		return 12;
	}

	@Override
	public int bps() {
		return 90*1024*8;
	}

	@Override
	public FrameFormat captureFormat() {
		return FrameFormat.NV21;
	}

	@Override
	public int captureFormatValue() {
		return captureFormat().value();
	}

	@Override
	public int onStart() {
		OpenCamera(true);
		startPreview(true);
		return 0;
	}

	@Override
	public void onStop() {
		OpenCamera(false);
		startPreview(false);
	}

	public interface QttCameraViewListener {
		void onCameraPreviewFrame(int width, int height, byte[] data, int format);
	}

	public int getDefaultWidth() {
		return defaultWidth;
	}

	public void setDefaultWidth(int defaultWidth) {
		this.defaultWidth = defaultWidth;
	}

	public int getDefaultHeight() {
		return defaultHeight;
	}

	public void setDefaultHeight(int defaultHeight) {
		this.defaultHeight = defaultHeight;
	}

	private native void nativePutFrame(ByteBuffer mFrameBytebuf, int len, int width, int height);
}
